﻿/**
 * ...
 * >author		João Vítor de Souza
 */

package com.cupcakeengine.media 
{
	
	import com.greensock.plugins.SoundTransformPlugin;
	import com.greensock.TweenLite;
	import com.greensock.TweenMax;	
	import flash.events.Event;
	import flash.events.EventDispatcher;	
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;	

	public class SoundManager extends EventDispatcher 
	{
		// ___________________________________________________________________ CONSTANTS
		
		private static var MUSIC_VOLUME	: int = 100;
		private static var SOUND_VOLUME	: int = 100;
		
		// ___________________________________________________________________ CLASS PROPERTIES		
		
		private var _pausePoint			: Number;
		
		// ___________________________________________________________________ INSTANCE PROPERTIES
		
		private static var _instance	: SoundManager;		
		private var _channel			: SoundChannel;		
		private var _channelSound		: SoundChannel;		
		private var _transform			: SoundTransform;
		private var _transformSound		: SoundTransform;
		private var _sound				: Sound;	
		
		private var _isMusicOn			: Boolean;
		private var _isSoundOn			: Boolean;		
		private var _isPlaying			: Boolean;
		
		private var _initialized		: Boolean;
		
		
		// ___________________________________________________________________ GETTERS AND SETTERS			
		
		public function get isMusicOn():Boolean { return _isMusicOn; }
		
		public function set isMusicOn(value:Boolean):void 
		{
			_isMusicOn = value;			
			
			if (_isMusicOn) {				
				if (!_isPlaying)				
				loopSound();				
			} else {
				stopLoop();
			}
		}
		
		public function get isSoundOn():Boolean { return _isSoundOn; }
		
		public function set isSoundOn(value:Boolean):void 
		{
			_isSoundOn = value;
			
			if (_isSoundOn) return;
			
			_channelSound.stop();
		}
		
		// ___________________________________________________________________ CONSTRUCTOR
		
		public function SoundManager (singleton:SingletonObligate) {}
		
		// ___________________________________________________________________ PUBLIC METHODS
		
		public static function getInstance () : SoundManager
		{
			if (!SoundManager._instance) SoundManager._instance = new SoundManager(new SingletonObligate());
			return SoundManager(SoundManager._instance);
		}
		
		public function init():void
		{	
			if (_initialized) return;
			_initialized = true;
			
			_isMusicOn = true;
			_isSoundOn = true;	
			
			_isPlaying = true;
			
			_channel = new SoundChannel();
			_channelSound = new SoundChannel();
			_transform = new SoundTransform();			
			_transformSound = new SoundTransform();						
		}
		
		public function playSound(sound:Sound):void
		{
			if (!_isSoundOn) return;
			_transformSound.volume = SOUND_VOLUME / 100;
			_channelSound = sound.play(0, 0, _transformSound);
		}				
		
		public function playMusic(sound:Sound):void
		{
			_sound = sound;			
			if (!_isMusicOn) return;			
			loopSound();
		}
		
		public function stopMusic():void
		{
			if (!_isMusicOn) {
				//_sound = null;
				return;
			}
			TweenLite.to(_transform, 1, { volume:0, onUpdate:updateChannel, onComplete:stopLoop  } );
		}			
		
		public function pauseSound():void
		{
			if (_channel == null) {
				_pausePoint = 0;
			} else {			
				_pausePoint = _channel.position;
				_channel.stop();	
			}
			
			_isPlaying = false;
		}
		
		public function unpauseSound():void
		{			
			if (_isPlaying) return;
			loopSound(_pausePoint);			
			_isPlaying = true;
		}		
		
		// ___________________________________________________________________ PRIVATE METHODS		
		
		private function loopSound(pausePoint:Number = 0):void
		{		
			if (!_isMusicOn || _sound == null) return;
			_isPlaying = true;
			_transform.volume = MUSIC_VOLUME / 100;
			_channel = _sound.play(pausePoint, 0, _transform);			
			_channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);			
		}
		
		private function stopLoop():void
		{
			if (_channel == null) return;
			_channel.stop();
			_channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComplete);
			_channel = null;
			
			_isPlaying = false;
		}
		
		private function updateChannel():void
		{			
			_channel.soundTransform = _transform;			
		}
		
		// ___________________________________________________________________ EVENTS
		
		private function onSoundComplete(e:Event):void 
		{			
			if (_channel != null){				
				_channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComplete);
				loopSound();
			}
		}
	}
}

class SingletonObligate {}
